/**
* @desc Auto Complete plugin.  Part of the Codereck Javascript Suite.
*
* @copyright Ryan Zec 2007-2009, All Right Reserved
*
* @license BSD (see LICENSE file included, the generic templete can be found at http://www.opensource.org/licenses/bsd-license.php)
*/
(function($)
{
	//create the codereck scope
	$.cr = $.cr || {};

    //initialization of codereck auto complete
	$.fn.auto_complete = function(options)
	{
		var cr_auto_complete = new $.cr.auto_complete(options, this);
	}

	//codereck auto complete class
	$.cr.auto_complete = function(options, element)
	{
		var self = this;
		var element_id = null;
		self.current_number = 0;

		if(element != 'undefined')
		{
			self.element = element;
			self.element_id = self.element.attr('id');
		}

		self.options = $.extend(
		{
            //url to get auto complete
			url: null,

            //css classes
			auto_complete_id: 'cr_auto_complete',
			auto_complete_class: 'cr_auto_complete',
			focus_class: 'cr_auto_complete_focus',

            //number of characters to load auto complete
			load_number: 3,

            //loads a value into a hidden field
            hidden_id: null,
            remote_data: null
		},
		options);

		self.options.div_count = 0;
		self.options.list_count = 0;

		//get the number of existing auto complete divs
		$('div[id^=' + self.options.auto_complete_id + ']').each(function(count)
		{
			self.options.div_count = count;
			self.options.div_count++;
		});

		self.options.div_count++;
		self.options.auto_complete_id += self.options.div_count;

		//create auto complete box
		$('body').append('<div id="' + self.options.auto_complete_id + '" class="' + self.options.auto_complete_class + '"></div>');
		self.hide_list();

		//TODO - need to move this into a function that is called when the list is shown and unbind when list is hiddden
		$(document).bind('click', function(event)
		{
	        if(!$(event.target).is('#' + self.element_id))
	        {
				self.hide_list();
			}
		});

		self.element.bind('keyup', function(event)
		{
			if(event.keyCode != 40 && event.keyCode != 38 && event.keyCode != 13)
			{
				//load auto complete after set number characters
				if($(this).val().length >= self.options.load_number)
				{
					//get the data and load the auot complete list
					self.options.remote_data = new $.cr.remote_data(
					{
						url: self.options.url,
						data:
						{
							search: $(this).val()
						},
						callback: function(object)
						{
							$('#' + self.options.auto_complete_id).empty();
							$('#' + self.options.auto_complete_id).append('<ul></ul>');

							object.each(function(key, record)
							{
								$('#' + self.options.auto_complete_id + ' ul').append('<li title="' + record.value + '">' + record.display + '</li>');
							});

                            self.show_list();
							self.options.list_count = 0;

							self.options.list_count = $('#' + self.options.auto_complete_id + ' li').length;
							$('#' + self.options.auto_complete_id + ' li').each(function(number)
							{
								$(this).bind('mouseenter', function()
								{
									self.focus(number);
								});
							});

		                    $('#' + self.options.auto_complete_id + ' li').bind('click', function(event)
							{
					   			self.update_value();
							});
						}
					});
				}
				else
				{
	                if($('#' + self.options.auto_complete_id).css('display') === 'block')
					{
						self.hide_list();
					}
				}
			}
		});

        $(self.element).bind('keydown', function(event)
		{
			switch(event.keyCode)
			{
				//down arrow
				case 40:
					var number = self.current_number + 1;
					self.focus(number);
					break;

				//up arrow
				case 38:
					var number = self.current_number - 1;
					self.focus(number);
					break;

				//enter
				case 13:
					/*we only want to prevent default behave of enter (which is submitting form) if they are hitting
					while the autocomplete is showing*/
					if($('#' + self.options.auto_complete_id).css('display') == 'block')
					{
						event.preventDefault();
						self.update_value();
					}
					break;

				//tab
				case 9:
					self.update_value();

				default:
					//nothing for now
					break;
			}
		});
	}

	$.extend($.cr.auto_complete.prototype, $.cr.core);
	$.extend($.cr.auto_complete.prototype,
	{
		hide_list: function()
		{
			$('#' + this.options.auto_complete_id).css('display', 'none');
			if($.browser.msie && parseInt($.browser.version) == '6')
			{
				this.select_show();
			}
			this.current_number = 0;
		},

		show_list: function()
		{
			if($('#' + this.options.auto_complete_id).html() != '')
			{
				//in case some other javascript has moved the position of this input, make sure the position is correct ofr the auto complete box
				this.update_position();
				$('#' + this.options.auto_complete_id).css('display', 'block');
                if($.browser.msie && parseInt($.browser.version) == '6')
				{
					this.select_hide();
				}
				this.resize_box();
				this.focus(this.current_number);
			}
		},

		focus: function(number)
		{
			if(number >= this.options.list_count)
			{
				number = this.options.list_count - 1;
			}

			if(number < 0)
			{
				number = 0;
			}

			this.current_number = number;
        	$('#' + this.options.auto_complete_id + ' li').removeClass(this.options.focus_class);
			$('#' + this.options.auto_complete_id + ' li:eq(' + number + ')').addClass(this.options.focus_class);
		},

		update_value: function()
		{
			//get the selected elements value
			var value = $('#' + this.options.auto_complete_id + ' li.' + this.options.focus_class).text();
			this.element.val(value);

            //load hidden field is provided
            if(this.options.hidden_id != null)
            {
                this.load_hidden_field();
            }

			this.hide_list();
		},

		//these next 2 function fixes the issue with select boxes showing through in IE 6
		select_hide: function()
		{
			var top_low = parseInt($('#' + this.options.auto_complete_id).offset().top);
			var top_high = parseInt($('#' + this.options.auto_complete_id).height() + top_low);

            var left_low = parseInt($('#' + this.options.auto_complete_id).offset().left);
			var left_high = parseInt($('#' + this.options.auto_complete_id).width() + left_low);

			$('select').each(function()
			{
				var element_top = parseInt($(this).offset().top);
				var element_left = parseInt($(this).offset().left);

				if(element_top >= top_low && element_top <= top_high && element_left >= left_low && element_left <= left_high)
				{
					$(this).css('display', 'none');
				}
			});
		},

		select_show: function()
		{
            $('select').each(function()
			{
				$(this).css('display', 'inline');
			});
		},

		resize_box: function()
		{
			if(this.element.width() > $('#' + this.options.auto_complete_id).width())
			{
				$('#' + this.options.auto_complete_id).width(this.element.width());
			}
		},

		update_position: function()
		{
            //setup css position for auto complete box
			var element_offset = this.element.offset();
			var element_height = this.element.height();
			var element_width = this.element.width();
			var top = parseInt(element_offset.top + element_height + 5);
			var left = parseInt(element_offset.left);

			$('#' + this.options.auto_complete_id).css(
			{
				'position': 'absolute',
				'top': top,
				'left': left
			});
		},

        load_hidden_field: function()
        {
            //get data for hidden field and load it
            var hidden_value = $('#' + this.options.auto_complete_id + ' li.' + this.options.focus_class).attr('title');
            $('#' + this.options.hidden_id).val(hidden_value);
        },

        document_event: function(type)
        {
        	var self = this;
        	if(type === 'bind')
        	{
        		$(document).bind('click.' + self.plugin_key, function(event)
        		{
				    if(!$(event.target).is('#' + self.element_id))
				    {
						self.hide_list();
					}
				});
			}
			else if(type === 'unbind');
			{
				$(document).unbind('click.' + self.plugin_key);
			}
		},

		data_loop: function(key, record)
		{
			alert('test');
		}
	});
})(jQuery);